package com.xiaoerkeji.eshop.request;

import android.os.Message;
import android.text.TextUtils;

import com.lt.base.BaseDataService;
import com.lt.bean.RequestResult;
import com.lt.common.DebugHelper;
import com.lt.common.ListUtils;
import com.lt.listener.DataServiceListener;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.Dispatcher;
import okhttp3.FormBody;
import okhttp3.MediaType;
import okhttp3.MultipartBody;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;

/**
 * https://github.com/square/okhttp
 */
public class BaseHttpRequest extends BaseDataService
{
    public static final int Http_OK = 200; // http请求成功
    public static final int Http_Error = 10000;
    protected final String TAG = this.getClass().getSimpleName();
    private static OkHttpClient mOkHttpClient;

    public BaseHttpRequest(DataServiceListener listener)
    {
        super(listener);
        if (mOkHttpClient == null)
        {
            OkHttpClient.Builder builder = new OkHttpClient.Builder();
            builder.connectTimeout(getTimeoutMillis(), TimeUnit.MILLISECONDS)
                    .readTimeout(getTimeoutMillis(), TimeUnit.MILLISECONDS);
            mOkHttpClient = builder.build();
        } else if (mOkHttpClient.connectTimeoutMillis() != getTimeoutMillis())
        {
            mOkHttpClient = mOkHttpClient.newBuilder()
                    .connectTimeout(getTimeoutMillis(), TimeUnit.MILLISECONDS)
                    .readTimeout(getTimeoutMillis(), TimeUnit.MILLISECONDS)
                    .build();
        }
    }


    /**
     * @return 获取超时时间
     */
    protected long getTimeoutMillis()
    {
        return 6000;
    }

    /**
     * @return 是否屏蔽证书
     */
    protected boolean isCertEnable()
    {
        return true;
    }

    /**
     * @return 添加header
     */
    protected Request formatHeaderRequest(Request.Builder builder)
    {
        builder = builder
                .addHeader("X-DEVICE", "android")
                .addHeader("X-UUID", "test");
        return builder.build();
    }

    public void cancelAll(Object tag)
    {
        if (mOkHttpClient == null)
        {
            return;
        }
        Dispatcher dispatcher = mOkHttpClient.dispatcher();
        synchronized (dispatcher)
        {
            for (Call call : dispatcher.queuedCalls())
            {
                if (tag.equals(call.request().tag()))
                {
                    call.cancel();
                }
            }
            for (Call call : dispatcher.runningCalls())
            {
                if (tag.equals(call.request().tag()))
                {
                    call.cancel();
                }
            }
        }
    }


//    public static SchemeRegistry getSchemeRegistry() {
//        try {
//            KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
//            trustStore.load(null, null);
//            SSLSocketFactory sf = new MySSLSocketFactory(trustStore);
//            sf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
//            HttpParams params = new BasicHttpParams();
//            HttpConnectionParams.setConnectionTimeout(params, 10000);
//            HttpConnectionParams.setSoTimeout(params, 10000);
//            HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
//            HttpProtocolParams.setContentCharset(params, HTTP.UTF_8);
//            SchemeRegistry registry = new SchemeRegistry();
//            registry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
//            registry.register(new Scheme("https", sf, 443));
//            return registry;
//        } catch (Exception e) {
//            return null;
//        }
//    }


    protected String getGetUrlByParams(String url, Map<String, String> map)
    {
        String result = url;
        if (map != null && !map.isEmpty())
        {
            String params = "";
            Iterator iter = map.entrySet().iterator();
            while (iter.hasNext())
            {
                Map.Entry entry = (Map.Entry) iter.next();
                params = params + "&" + entry.getKey() + "=" + entry.getValue();
            }
            if (!TextUtils.isEmpty(params))
            {
                params = params.substring(1, params.length());
                result = result + "?" + params;
            }
        }
        return result;
    }

    /**
     * 创建请求的参数body
     */
    protected RequestBody getRequestBody(Map<String, String> map)
    {
        FormBody.Builder builder = new FormBody.Builder();
        if (map != null && !map.isEmpty())
        {
            for (Map.Entry<String, String> entry : map.entrySet())
            {
                builder.add(entry.getKey(), entry.getValue());
            }
        }
        return builder.build();
    }

    /**
     * get方法，把参数带进去
     */
    protected String getUrlWithParams(String url, Map<String, String> map)
    {
        if (map == null || map.isEmpty())
        {
            return url;
        }
        StringBuilder sb = new StringBuilder();
        for (Map.Entry<String, String> entry : map.entrySet())
        {
            sb.append("&");
            sb.append(entry.getKey());
            sb.append("=");
            sb.append(entry.getValue());
        }
        String str = sb.toString();
        str = str.replaceFirst("&", "?");
        return url + str;
    }


    public void post(final int what, final String url, Map<String, String> map)
    {
        post(what, url, getRequestBody(map));
    }

    public void postJson(final int what, final String url, final String json)
    {
        log(json);
        MediaType JSON = MediaType.parse("application/json; charset=utf-8");
        RequestBody body = RequestBody.create(JSON, json);
        post(what, url, body);
    }

    public void postText(final int what, final String url, final String text)
    {
        MediaType TEXT = MediaType.parse("text/plain");
        RequestBody body = RequestBody.create(TEXT, text);
        post(what, url, body);
    }

    protected void post(final int what, final String url, RequestBody body)
    {
        Request.Builder builder = new Request.Builder().url(url).post(body);
        Call call = mOkHttpClient.newCall(formatHeaderRequest(builder));
        call.enqueue(new Callback()
        {
            @Override
            public void onFailure(Call call, IOException e)
            {
                sendMessage(url, what, null, e);
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException
            {
                sendMessage(url, what, response, null);
            }
        });
    }

    public void postJson(final int what, final String url, final String json, final String mark)
    {
        log(json);
        MediaType JSON = MediaType.parse("application/json; charset=utf-8");
        RequestBody body = RequestBody.create(JSON, json);
        post(what, url, body, mark);
    }

    protected void post(final int what, final String url, RequestBody body, String mark)
    {
        Request.Builder builder = new Request.Builder().url(url).post(body);
        Call call = mOkHttpClient.newCall(formatHeaderRequest(builder));
        call.enqueue(new Callback()
        {
            @Override
            public void onFailure(Call call, IOException e)
            {
                sendMessage(url, what, mark, null, e);
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException
            {
                sendMessage(url, what, mark, response, null);
            }
        });
    }

    protected void postFile(final int what, final String url,
                            final Map<String, String> params, final String fileKey, final File file)
    {
        List<File> list = null;
        if (file != null)
        {
            list = new ArrayList<>();
            list.add(file);
        }
        postFiles(url, what, params, fileKey, list);
    }

    protected void postFiles(final String url, final int what,
                             final Map<String, String> params, final String fileKey, List<File> fileList)
    {
        MultipartBody.Builder builder = new MultipartBody.Builder();
        //设置类型
        builder.setType(MultipartBody.FORM);
        if (params != null && !params.isEmpty())
        {
            //加参数
            for (String key : params.keySet())
            {
                builder.addFormDataPart(key, params.get(key));
            }
        }
        //加文件
        for (File file : fileList)
        {
            builder.addFormDataPart(fileKey, file.getName(), RequestBody.create(null, file));
        }
        RequestBody body = builder.build();
        post(what, url, body);
    }

    public void postFiles(final String url, final int what, final Map<String, String> params,
                          final List<String> fileKeys, List<File> fileList)
    {
        MultipartBody.Builder builder = new MultipartBody.Builder();
        //设置类型
        builder.setType(MultipartBody.FORM);
        if (params != null && !params.isEmpty())
        {
            //加参数
            for (String key : params.keySet())
            {
                builder.addFormDataPart(key, params.get(key));
            }
        }
        //加文件
        if (ListUtils.getSize(fileKeys) > 0 && ListUtils.getSize(fileList) > 0)
        {
            int len = Math.min(ListUtils.getSize(fileKeys), ListUtils.getSize(fileList));
            for (int i = 0; i < len; i++)
            {
                builder.addFormDataPart(fileKeys.get(i), fileList.get(i).getName(), RequestBody.create(null, fileList.get(i)));
            }
        }
        RequestBody body = builder.build();
        post(what, url, body);
    }


    /**
     * 下载文件，返回文件的路径
     *
     * @param url      下载链接
     * @param dir      保存到的文件夹
     * @param fileName 保存的文件名
     */
    protected void downloadFile(final int what, final String url, final File dir, final String fileName)
    {
        Request.Builder builder = new Request.Builder().url(url);
        Call call = mOkHttpClient.newCall(formatHeaderRequest(builder));
        call.enqueue(new Callback()
        {
            @Override
            public void onFailure(Call call, IOException e)
            {
                sendMessage(url, what, null, e);
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException
            {
                RequestResult result = new RequestResult();
                Message message = new Message();
                InputStream is = null;
                byte[] buf = new byte[2048];
                int len = 0;
                FileOutputStream fos = null;
                //储存下载文件的目录
                if (!dir.exists())
                {
                    dir.mkdirs();
                }
                File file = new File(dir, fileName);
                try
                {
                    is = response.body().byteStream();
                    long total = response.body().contentLength();
                    fos = new FileOutputStream(file);
                    long sum = 0;
                    while ((len = is.read(buf)) != -1)
                    {
                        fos.write(buf, 0, len);
                        sum += len;
                        int progress = (int) (sum * 1.0f / total * 100);
                        //下载中更新进度条
//                        listener.onDownloading(progress);
                    }
                    fos.flush();
                    //下载完成
                    result.status = 200;
                    result.what = what;
                    result.data = file.getAbsolutePath();
                    message.what = what;
                    message.obj = result;
                    sendMessage(message);
                } catch (Exception e)
                {
                    result.status = 500;
                    result.what = what;
                    result.data = null;
                    result.message = "下载失败！" + e.getMessage();
                    message.what = what;
                    message.obj = result;
                    sendMessage(message);
                } finally
                {
                    try
                    {
                        if (is != null)
                        {
                            is.close();
                        }
                        if (fos != null)
                        {
                            fos.close();
                        }
                    } catch (IOException e)
                    {
                        e.printStackTrace();
                    }
                }
            }
        });
    }

    protected void get(final int what, final String url)
    {
//        TrafficStats.setThreadStatsTag(10000);
        Request.Builder builder = new Request.Builder().url(url);
        //可以省略，默认是GET请求
        builder.method("GET", null);
        Call call = mOkHttpClient.newCall(formatHeaderRequest(builder));
        call.enqueue(new Callback()
        {
            @Override
            public void onFailure(Call call, IOException e)
            {
                sendMessage(url, what, null, e);
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException
            {
                sendMessage(url, what, response, null);
            }
        });
    }

    public void get(final int what, final String url, Map<String, String> map)
    {
        get(what, getUrlWithParams(url, map));
    }


    protected void sendMessage(String url, int what, Response response, IOException e)
    {
        RequestResult result = new RequestResult();
        result.status = Http_Error;
        result.what = what;
        if (e != null)
        {
            result.message = e.getMessage();
        } else if (response != null)
        {
            result.status = response.code();
            if (response.isSuccessful())
            {
                result.status = Http_OK;
            }
            if (response.body() != null)
            {
                try
                {
                    result.data = response.body().string();
                } catch (IOException e1)
                {
                    e1.printStackTrace();
                }
            }
        } else
        {
            result.message = "Unknown Error";
        }
        StringBuilder sb = new StringBuilder();
        sb.append("request url:");
        sb.append(url);
        sb.append("\r\nwhat:");
        sb.append(what);
        sb.append("\r\nhttp status：");
        sb.append(response == null ? Http_Error : response.code());
        sb.append("\r\nmessage:");
        sb.append(result.message);
        sb.append("\r\ndata:");
        sb.append(result.data);
        DebugHelper.e(TAG, sb.toString());
        if (what == 0)
        {
            return;
        }
        Message msg = new Message();
        msg.what = what;
        msg.obj = result;
        if (getSoftDataServiceListener() != null && getSoftDataServiceListener().get() != null)
        {
            getSoftDataServiceListener().get().sendMessage(msg);
        }
    }


    protected void sendMessage(String url, int what, String mark, Response response, IOException e)
    {
        RequestResult result = new RequestResult();
        result.status = Http_Error;
        result.what = what;
        if (e != null)
        {
            result.message = e.getMessage();
        } else if (response != null)
        {
            result.status = response.code();
            if (response.isSuccessful())
            {
                result.status = Http_OK;
            }
            if (response.body() != null)
            {
                try
                {
                    result.data = response.body().string();
                } catch (IOException e1)
                {
                    e1.printStackTrace();
                }
            }
        } else
        {
            result.message = "Unknown Error";
        }
        result.mark = mark;
        StringBuilder sb = new StringBuilder();
        sb.append("request url:");
        sb.append(url);
        sb.append("\r\nwhat:");
        sb.append(what);
        sb.append("\r\nhttp status：");
        sb.append(response == null ? Http_Error : response.code());
        sb.append("\r\nmessage:");
        sb.append(result.message);
        sb.append("\r\ndata:");
        sb.append(result.data);
        sb.append("\r\nmark:");
        sb.append(result.mark);
        DebugHelper.e(TAG, sb.toString());
        if (what == 0)
        {
            return;
        }
        Message msg = new Message();
        msg.what = what;
        msg.obj = result;
        if (getSoftDataServiceListener() != null && getSoftDataServiceListener().get() != null)
        {
            getSoftDataServiceListener().get().sendMessage(msg);
        }
    }


    /**
     * header不支持中文以及中文符号
     */
    protected static String encodeHeadValueInfo(String header)
    {
        if (TextUtils.isEmpty(header))
        {
            return header;
        }
        StringBuilder sb = new StringBuilder();
        for (int i = 0, length = header.length(); i < length; i++)
        {
            char c = header.charAt(i);
            if (c <= '\u001f' || c >= '\u007f')
            {
                sb.append(String.format("\\u%04x", (int) c));
            } else
            {
                sb.append(c);
            }
        }
        return sb.toString();
    }

    protected void log(String msg)
    {
        DebugHelper.w(TAG, msg);
    }
}
